/*****************************************************************************
 * Copyright (C) Stacy Curl. All rights reserved.                            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 *****************************************************************************/
package picounit.features.test_finder;


import picounit.Marker;
import picounit.PicoUnitException;
import picounit.TestFilter;
import picounit.features.base.TestFinder;
import picounit.features.class_finder.ClassFinder;
import picounit.features.classloader.PackageUtil;
import picounit.features.coverage_measuring.SuiteDecorator;
import picounit.features.failures_first.ProblemTracker;
import picounit.features.failures_first.StatusPersister;
import picounit.features.test_factory.TestFactory;
import picounit.features.test_instantiator.TestInstantiator;
import junit.framework.TestSuite;

class DirectoryScanningTestFinder implements TestFinder {
	private final PackageUtil packageUtil = new PackageUtil();

	private final ClassFinder classFinder;
	private final ClassLoader classLoader;
	private final TestInstantiator testInstantiator;
	private final StatusPersister statusPersister;
	private final TestFactory testFactory;
	private final SuiteDecorator suiteDecorator;
	private final ProblemTracker problemTracker;

	private final ObjectReloader objectReloader;

	public DirectoryScanningTestFinder(StatusPersister statusPersister, ClassFinder classFinder,
		SuiteDecorator suiteDecorator, TestFactory testFactory, TestInstantiator testInstantiator,
		ClassLoader classLoader, ProblemTracker problemTracker, ObjectReloader objectReloader) {

		this.statusPersister = statusPersister;
		this.classFinder = classFinder;
		this.suiteDecorator = suiteDecorator;
		this.testFactory = testFactory;
		this.testInstantiator = testInstantiator; 
		this.classLoader = classLoader;
		this.problemTracker = problemTracker;
		this.objectReloader = objectReloader;
	}
	
	// TODO: Figure out how to use class reloading on any class instances inside the markers
	public TestSuite findTests(String name, Class<?> startingClass, Marker marker, TestFilter testFilter) {
		try {
			Marker reloadedMarker = objectReloader.reload(marker);
			
			statusPersister.inform(startingClass, testFilter);

			TestSuite testSuite = new SortedTestSuite(getName(name, startingClass), problemTracker);

			TestSuite ignoredTestSuite = new TestSuite("Ignored Tests");

			classFinder.findClasses(startingClass, new AddTestFindAction(testFilter, classLoader,
				testSuite, ignoredTestSuite, reloadedMarker, testInstantiator, testFactory));

			if (testSuite.testCount() == 0) {
				testSuite.addTest(new NoTestsFoundTestCase(startingClass, reloadedMarker));
			}

			if (ignoredTestSuite.countTestCases() > 0) {
				testSuite.addTest(ignoredTestSuite);
			}

			return suiteDecorator.decorate(testSuite);
		}
		catch (RuntimeException runtimeException) {
			throw PicoUnitException.wrap(runtimeException);
		}
	}

	private String getName(String name, Class startingClass) {
		return name != null ? name : packageUtil.packageName(startingClass);
	}
}
